
;数据段，用来存储数据
DATA SEGMENT
    ;欢迎界面
    HELLOPIC    DB '           ',0DH,0AH
                DB '           ',0DH,0AH
                DB '           ',0DH,0AH
                DB '            /##      /##       /######       /##   /##       /########',0DH,0AH
                DB '           | ###    /###      |_  ##_/      | ### | ##      | ##_____/',0DH,0AH
                DB '           | ####  /####        | ##        | ####| ##      | ##      ',0DH,0AH
                DB '           | ## ##/## ##        | ##        | ## ## ##      | #####   ',0DH,0AH
                DB '           | ##  ###| ##        | ##        | ##  ####      | ##__/   ',0DH,0AH
                DB '           | ##\  # | ##        | ##        | ##\  ###      | ##      ',0DH,0AH
                DB '           | ## \/  | ##       /######      | ## \  ##      | ########',0DH,0AH
                DB '           |__/     |__/      |______/      |__/  \__/      |________/',0DH,0AH
                DB '                  /#######        /#######         /######            ',0DH,0AH
                DB '                 | ##__  ##      | ##__  ##       /##__  ##           ',0DH,0AH
                DB '                 | ##  \ ##      | ##  \ ##      | ##  \ ##           ',0DH,0AH
                DB '                 | #######/      | #######/      | ##  | ##           ',0DH,0AH
                DB '                 | ##____/       | ##__  ##      | ##  | ##           ',0DH,0AH
                DB '                 | ##            | ##  \ ##      | ##  | ##           ',0DH,0AH
                DB '                 | ##            | ##  | ##      |  ######/           ',0DH,0AH
                DB '                 |__/            |__/  |__/       \______/            ',0DH,0AH
                DB '         ',0DH,0AH
                DB '         ',0DH,0AH
                DB '                            press any key to start                    ',0DH,0AH
                DB '$'
    ;难度选择界面
    HARD_CHOICEPIC  DB '                           __  __  ______  _   _  _    _                ',0DH,0AH
                    DB '                          |  \/  ||  ____|| \ | || |  | |               ',0DH,0AH
                    DB '                          | \  / || |__   |  \| || |  | |               ',0DH,0AH
                    DB '                          | |\/| ||  __|  | . ` || |  | |               ',0DH,0AH
                    DB '                          | |  | || |____ | |\  || |__| |               ',0DH,0AH
                    DB '                          |_|  |_||______||_| \_| \____/                ',0DH,0AH
                    DB '                           _____  _____  __  __  _____   _       ______ ',0DH,0AH
                    DB '                /\        / ____||_   _||  \/  ||  __ \ | |     |  ____|',0DH,0AH
                    DB '               /  \      | (___    | |  | \  / || |__) || |     | |__   ',0DH,0AH
                    DB '              / /\ \      \___ \   | |  | |\/| ||  ___/ | |     |  __|  ',0DH,0AH
                    DB '             / ____ \  _  ____) | _| |_ | |  | || |     | |____ | |____ ',0DH,0AH
                    DB '            /_/    \_\(_)|_____/ |_____||_|  |_||_|     |______||______|',0DH,0AH
                    DB '             ____     _   _   ____   _____   __  __            _        ',0DH,0AH
                    DB '            |  _ \   | \ | | / __ \ |  __ \ |  \/  |    /\    | |       ',0DH,0AH
                    DB '            | |_) |  |  \| || |  | || |__) || \  / |   /  \   | |       ',0DH,0AH
                    DB '            |  _ <   | . ` || |  | ||  _  / | |\/| |  / /\ \  | |       ',0DH,0AH
                    DB '            | |_) |_ | |\  || |__| || | \ \ | |  | | / ____ \ | |____   ',0DH,0AH
                    DB '            |____/(_)|_| \_| \____/ |_|  \_\|_|  |_|/_/    \_\|______|  ',0DH,0AH
                    DB '              _____     _    _            _____   _____                 ',0DH,0AH
                    DB '             / ____|   | |  | |    /\    |  __ \ |  __ \                ',0DH,0AH
                    DB '            | |        | |__| |   /  \   | |__) || |  | |               ',0DH,0AH
                    DB '            | |        |  __  |  / /\ \  |  _  / | |  | |               ',0DH,0AH
                    DB '            | |____  _ | |  | | / ____ \ | | \ \ | |__| |               ',0DH,0AH
                    DB '             \_____|(_)|_|  |_|/_/    \_\|_|  \_\|_____/                ',0DH,0AH
                    DB '                                                                        ',0DH,0AH
                    DB '                                                                        ',0DH,0AH
                    DB '$'
    
    ;主数据，存储地雷的位置，有雷的地方0FFH，没有雷0H，图大小为80*100的二维数组
    MINE_TABLE      DB  40*60  DUP(0H)
    ;判断表，记录第i行第j列的元素四周雷的个数,取值0~8
    JUDGE_TABLE     DB  40*60  DUP(0H)
    ;可见表，记录已经被扫开的区域为FFH，特别的用0FH记录标记为雷的区域，不可见区域标记为0H
    VISIBLE_TABLE   DB  40*60  DUP(0H)
    ;未排地雷个数
    MINE_LEFT       DB  0H
    ;实际三个表的长宽,总雷数
    REAL_WIDTH           DB  0H
    REAL_HEIGHT          DB  0H
    MINE_NUM        DB  0H
    ;难度，分为三个等级:分别为0,1,2
    ;A.10*20,10个雷
    ;B.20*40,40个雷
    ;C.20*40,80个雷
    HARD_LEVEL      DB  0H
    ;###########属性数据###########
    ;主图距离屏幕左上角的偏移量
    MAGIN_LEFT      DB  0H
    MAGIN_TOP       DB  0H
    ;当前处于表中位置
    TABLE_X         DB  0H
    TABLE_Y         DB  0H
    ;临时变量
    TEMP_X          DW  0H
    TEMP_Y          DW  0H
    ;对应处于屏幕位置
    SCREEN_X        DW  0
    SCREEN_Y        DW  0
DATA ENDS

;附加段，用来保存过程和宏
EXTRA SEGMENT
    ;生成1-X的随机数，存储在RESULT中
    GET_RAND MACRO  X,RESULT
        MOV AX, X   ;产生从1到AX之间的随机数
        MOV DX, 41H ;用端口41H，或者上面说的其他端口也行
        OUT DX, AX  ;
        IN  AX,DX;产生的随机数AL
        MOV RESULT,AL;
        ENDM

    ;设置屏幕分辨率640*480，16色图形方式
    SETSCREEN MACRO
        MOV AH,0    
        MOV AL,12H
        INT 10H
        ENDM
    
    ;根据键入获取难度等级，存储在HARD_LEVEL中
    GET_HARD_LEVEL MACRO HARD_LEVEL
        ;键入
        BEGIN:
        MOV AH,0
        INT 16H
        ;判断键入字符是否在a-c之间
        CMP AL,'a'
        JL  BEGIN
        CMP AL,'c'
        JG  BEGIN
        SUB AL,'a'
        MOV HARD_LEVEL,AL
        ENDM

    ;########画细点宏########
    ;参数：页面、Y坐标、X坐标、颜色，通过将AH放入0CH,通过10H中断来描点
    ;0黑色 1蓝色 2绿色 3青色 4红色 5紫色 6橙色 7白色 8灰色
    POINT_THIN MACRO PAGE,ROW,COLUMN,COLOR
        PUSH AX
        PUSH BX
        PUSH CX
        PUSH DX
        MOV AH,0CH
        MOV AL,COLOR
        MOV BH,PAGE
        MOV DX,ROW
        MOV CX,COLUMN
        INT 10H
        POP DX
        POP CX
        POP BX
        POP AX
    ENDM

    ;########根据逻辑坐标计算绝对坐标########
    CALCULATE_POS MACRO TABLE_X,TABLE_Y,SCREEN_X,SCREEN_Y
        MOV AL,TABLE_X
        MOV BL,16
        MUL BL
        MOV SCREEN_X,16
        MOV AL,TABLE_Y
        MOV BL,16
        MUL BL
        MOV SCREEN_Y,16
    ENDM

    ;########画16*16矩形宏########
    DRAW_REC_H MACRO ROW,COLUMN,COLOR
    ;参数：页面、Y坐标、X坐标、颜色，通过将AH放入0CH,通过10H中断来描点
    ;0黑色 1蓝色 2绿色 3青色 4红色 5紫色 6橙色 7白色 8灰色
        ;ROW,COLUMN,COLOR分别保存在DX,CX，AL中
        PUSH DX
        PUSH CX
        PUSH AX
        MOV DX,SCREEN_Y
        MOV CX,SCREEN_X
        MOV AL,2
        CALL DRAW_REC
        POP AX
        POP CX
        POP DX
    ENDM 

    ;########根据[x][y]获得地址，存放在SI########
    POSITION_REC MACRO x,y,SI
        PUSH DX
        PUSH CX
        PUSH AX
        MOV SI,y
        MUL 60
        ADD SI,AX
        DEC SI ;产生偏移地址
        POP AX
        POP CX
        POP DX
    ENDM

   ;########判断[x][y]是否越界########
    CHECK_OUT_BOUND MACRO x,y
        PUSH DX
        PUSH CX
        PUSH AX
        
        CMP x,0
        JC  FIN_1   
        JMP COM_Y
        
        COM_Y:
        CMP 2400,y
        JC FIN_1
        
        FIN_1: RET
        POP AX
        POP CX
        POP DX
    ENDM
    
    ;########根据定义的三个表绘制图形界面宏########
    ; DRAWSCREEN MACRO    MINE_TABLE,JUDGE_TABLE,VISIBLE_TABLE,REAL_WIDTH,REAL_HEIGHT,TABLE_X,TABLE_Y,SCREEN_X,SCREEN_Y
    ;     LOCAL LOOP3
    ;     LOCAL LOOP4
    ;     LOCAL INVISIBEL
    ;     LOCAL MINE
    ;     LOCAL NUM
    ;     LOCAL NUM0
    ;     LOCAL NEXT
    ;     MOV TABLE_X,0
    ;     MOV TABLE_Y,0
    ;     LOOP3:
    ;         MOV TABLE_X,0
    ;         ;TEMP_X存入REAL_WIDTH*TABLE_Y
    ;         MOV AL,REAL_WIDTH
    ;         MUL TABLE_Y
    ;         MOV TEMP_X,AX
    ;         LOOP4:
    ;             CMP VISIBLE_TABLE[TEMP_X][TABLE_X],0
    ;             JZ INVISIBEL
    ;             CMP VISIBLE_TABLE[TEMP_X][TABLE_X],0FH
    ;             JZ MINE
    ;             CMP VISIBLE_TABLE[TEMP_X][TABLE_X],0FFH
    ;             JZ NUM0
    ;             CALCULATE_POS TABLE_X,TABLE_Y,SCREEN_X,SCREEN_Y
    ;             INVISIBEL:
    ;                 DRAW_REC SCREEN_Y,SCREEN_X,TEMP_X,TEMP_Y,1
    ;                 JUP NEXT
    ;             MINE:
    ;                 DRAW_REC SCREEN_Y,SCREEN_X,TEMP_X,TEMP_Y,2
    ;                 JUP NEXT
    ;             NUM:
    ;                 CMP JUDGE_TABLE[TEMP_X][TABLE_X],0H
    ;                 JNZ NUM1
    ;                 DRAW_REC SCREEN_Y,SCREEN_X,TEMP_X,TEMP_Y,8
    ;                 JUP NEXT
    ;                 NUM1:
    ;                     DRAW_REC SCREEN_Y,SCREEN_X,TEMP_X,TEMP_Y,8
    ;                     ;TEMP_Y*2
    ;                     MOV AL,TABLE_X
    ;                     CBW
    ;                     MOV TEMP_Y,AX
    ;                     SHL TEMP_Y,1
    ;                     ;移动光标至（TEMP_Y,TABLE_X）
    ;                     MOV AH,1
    ;                     MOV BH,0
    ;                     MOV DH,BYTE PTR TEMP_Y
    ;                     MOV DL,TABLE_X
    ;                     INT 10H
    ;                     ;打印字符
    ;                     MOV DL,JUDGE_TABLE[TEMP_X][TABLE_X]
    ;                     MOV AH,6
    ;                     INT 21H
    ;                     JUP NEXT
    ;             NEXT:
    ;             INC TEMP_X
    ;             ;DI存入REAL_WIDTH
    ;             MOV AL,REAL_WIDTH
    ;             CBW
    ;             MOV DI,AX
    ;             CMP BYTE PTR DI,TEMP_X
    ;             JNZ LOOP4
    ;         INC TEMP_Y
    ;         ;SI存入REAL_HEIGHT
    ;         MOV AL,REAL_HEIGHT
    ;         CBW
    ;         MOV SI,AX
    ;         CMP BYTE PTR SI,TEMP_Y
    ;         JNZ LOOP3
    ; ENDM
    
EXTRA ENDS

;代码段，程序主指令流
CODE SEGMENT
    ASSUME CS:CODE,DS:DATA,ES:EXTRA

    ;########画16*16矩形过程########
    ;ROW,COLUMN,COLOR分别保存在DX,CX，AL中
    DRAW_REC PROC 
        PUSH CX
        PUSH DX
        PUSH SI
        PUSH DI
        MOV BX,CX
        MOV AX,DX
        MOV SI,16    ;字符高16
        MOV DI,16    ;字符宽8
        LOOP1:
            MOV DI,16
            ADD CX,16
            LOOP2:
                POINT_THIN 0,DX,CX,3
                DEC CX
                DEC DI
                JNZ  LOOP2
            INC DX
            DEC SI
            JNZ LOOP1
        POP DI
        POP SI
        POP DX
        POP CX
        RET
    DRAW_REC ENDP


    ;########初始化MINE_TABLE过程########
    MINE_TABLE_GENERATE PROC
    PUSH AX
    PUSH BX
    PUSH CX
    PUSH DX
    PUSH SI
    PUSH DS
    MOV CX, MINE_NUM 
    DEC CX
    NEXT41: GET_RAND REAL_WIDTH,AL ;产生从1到行数WIDTH之间的随机数作为雷的x坐标
          GET_RAND REAL_HEIGHT,BL ;产生从1到行数HEIGHT之间的随机数作为雷的y坐标
          MOV SI,BL
          MUL 60
          ADD SI,AX
          DEC SI ;产生偏移地址
          CMP  MINE_TABLE[SI],0
          JC NEXT1  ;若不大于，转向NEXT1
          JMP NEXT  ;否则，转到NEXT
          ;检查是否重复坐标
          NEXT1: MOV MINE_TABLE[SI],1
                 JMP LOOP41
    LOOP41 NEXT41

    POP DX
    POP CX
    POP BX
    POP AX
    POP DS
    POP SI
    MINE_TABLE_GENERATE ENDP

    
    ;########初始化JUDGE_TABLE过程########
    JUDGE_TABLE_GENERATE PROC
    PUSH AX
    PUSH BX
    PUSH CX
    PUSH DX
    PUSH SI
    PUSH DS
    
    MOV AX,MINE_TABLE   ;在judge table中分别把每个雷周围的数字加1
    MOV DS,AX
    MOV SI,0
    MOV CX,MINE_NUM
    LOOP_JUDGE_NUM: 
     MOV DH,x[SI]
     MOV DL,y[SI]
     CALL ARER1
     CALL ARER2
     CALL ARER3
     CALL ARER4
     CALL ARER5
     CALL ARER6
     CALL ARER7
     CALL ARER8
     INC SI
    LOOP LOOP_JUDGE_NUM

    JMP JUDGE_END  ;直接结束judge

    ARER1:
     CMP DH,1
     JB JU_1
     CMP DL,2
     JB JU_1
     MOV BX,DX
     DEC BH
     SUB BL,2
     CALL MUL_POSITION
     JU_1: NOP
     RET

    ARER2:
     CMP DH,1
     JB JU_2
     MOV BX,DX
     DEC BH
     CALL MUL_POSITION
     JU_2: NOP
     RET

    ARER3:
     CMP DH,1
     JB JU_3
     CMP DL,16
     JA JU_3
     MOV BX,DX
     DEC BH
     ADD BL,2
     CALL MUL_POSITION
     JU_3: NOP
     RET

    ARER4:
     CMP DL,2
     JB JU_4
     MOV BX,DX
     SUB BL,2
     CALL MUL_POSITION
     JU_4: NOP
     RET

    ARER5:
     CMP DL,16
     JA JU_5
     MOV BX,DX
     ADD BL,2
     CALL MUL_POSITION
     JU_5: NOP
     RET

    ARER6:
     CMP DH,8
     JA JU_6
     CMP DL,2
     JB JU_6
     MOV BX,DX
     INC BH
     SUB BL,2
     CALL MUL_POSITION
     JU_6: NOP
     RET

    ARER7:
     CMP DH,8
     JA JU_7
     MOV BX,DX
     INC BH
     CALL MUL_POSITION
     JU_7: NOP
     RET

    ARER8:
     CMP DH,8
     JA JU_8
     CMP DL,16
     JA JU_8
     MOV BX,DX
     INC BH
     ADD BL,2
     CALL MUL_POSITION
     JU_8: NOP
     RET

    MUL_POSITION:  ;获得MINE_TABLE中的位置
     MOV AL,20
     MUL BH
     MOV BH,0
     ADD AX,BX
     MOV BX,AX
     MOV AL,DS:[BX]
     CMP AL,1
     JE FINISHM
     INC AL
     MOV DS:[BX],AL
    
    FINISHM:  RET

    JUDGE_END: POP DS
               POP SI
               POP DX
               POP CX
               POP BX
               POP AX
               RET

JUDGE_TABLE_GENERATE ENDP






START:
        ;初始化代码段
        MOV AX,DATA
        MOV DS,AX
        MOV AX,EXTRA
        MOV ES,AX
        ;###########绘制欢迎界面,等待任意键输入###########
        SETSCREEN;刷新页面
        LEA DX,HELLOPIC   ;打印欢迎界面
        MOV AH,09H
        INT 21H   
        MOV AX,1;等待任意键入
        INT 16H
        ;进入难度选择界面
        SETSCREEN;刷新页面
        ;###########绘制难度选择界面,等待输入难度(A,B,C)###########
        LEA DX,HARD_CHOICEPIC   ;打印难度选择界面
        MOV AH,09H
        INT 21H   
        GET_HARD_LEVEL  HARD_LEVEL;根据键入获取难度等级
        ;###########初始化参数###########

        ;###########根据定义的三个表绘制图形界面###########
REFRESHSCREEN:
        SETSCREEN
        DRAW_REC_H SCREEN_Y,SCREEN_X,2
        
        MOV AX,1;等待任意键入
        INT 16H
        ;结束程序
        MOV AH,4CH
        INT 21H
CODE ENDS
        END START


